﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using GalaSoft.MvvmLight;
using ALiteTeam.PackageTracer.Data;
using ALiteTeam.PackageTracer.Core;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using ALiteTeam.PackageTracer.Core.Impl;
using System.Collections.ObjectModel;

namespace ALiteTeam.PackageTracer.ViewModel
{
    public class DetailsViewModel : ViewModelBase
    {
        public static readonly Guid INITIALIZE = Guid.NewGuid();
        public static readonly Guid REFRESH = Guid.NewGuid();

        private DeliveryOrder _Order;
        private Delivery _Delivery;

        private Microsoft.Phone.Controls.PerformanceProgressBar _PerfProgressBar;

        public IDeliveryOperate DeliveryOp { get; set; }
        public IOrderOperate OrderOp { get; set; }
        public IQueryService QueryOp { get; set; }

        /// <summary>
        /// 快递商电话
        /// </summary>
        public string Phone { get { return _Delivery.Phone; } }

        public DetailsViewModel()
        {
            if (IsInDesignMode == false)
            {
                this.DeliveryOp = DeliveryDataOp.Instance;
                this.OrderOp = new OrderOp();

                Messenger.Default.Register<Guid>(this, INITIALIZE, Initialize);
                Messenger.Default.Register<NotificationMessage>(this, REFRESH, UpdateDetails);

                this.SaveCommand = new RelayCommand(Save);
            }
        }

        #region 绑定属性
        /// <summary>
        /// The <see cref="OrderNo" /> property's name.
        /// </summary>
        public const string OrderNoPropertyName = "OrderNo";
        private string mOrderNo = string.Empty;

        /// <summary>
        /// Gets the OrderNo property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string OrderNo
        {
            get
            {
                return mOrderNo;
            }
            set
            {
                if (mOrderNo == value)
                {
                    return;
                }
                mOrderNo = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(OrderNoPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsIndeterminate" /> property's name.
        /// </summary>
        public const string IsIndeterminatePropertyName = "IsIndeterminate";
        private bool mIsIndeterminate = false;

        /// <summary>
        /// Gets the IsIndeterminate property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool IsIndeterminate
        {
            get
            {
                return mIsIndeterminate;
            }
            set
            {
                if (mIsIndeterminate == value)
                {
                    return;
                }
                mIsIndeterminate = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(IsIndeterminatePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="Title" /> property's name.
        /// </summary>
        public const string TitlePropertyName = "Title";
        private string mTitle = string.Empty;

        /// <summary>
        /// Gets the Title property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string Title
        {
            get
            {
                return mTitle;
            }

            set
            {
                if (mTitle == value)
                {
                    return;
                }
                mTitle = value;
                // Update bindings, no broadcast
                RaisePropertyChanged(TitlePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="DisplayName" /> property's name.
        /// </summary>
        public const string DisplayNamePropertyName = "DisplayName";
        private string mDisplayName = string.Empty;

        /// <summary>
        /// Gets the DisplayName property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public string DisplayName
        {
            get
            {
                return mDisplayName;
            }
            set
            {
                if (mDisplayName == value)
                {
                    return;
                }
                mDisplayName = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(DisplayNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="RefreshDuration" /> property's name.
        /// </summary>
        public const string RefreshDurationPropertyName = "RefreshDuration";
        private double mRefreshDuration = 0;

        /// <summary>
        /// Gets the RefreshDuration property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public double RefreshDuration
        {
            get
            {
                return mRefreshDuration;
            }
            set
            {
                if (mRefreshDuration == value)
                {
                    return;
                }
                mRefreshDuration = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(RefreshDurationPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="Details" /> property's name.
        /// </summary>
        public const string DetailsPropertyName = "Details";
        private ObservableCollection<ALiteTeam.PackageTracer.Data.QueryResult.Detail> mDetails = null;

        /// <summary>
        /// Gets the Details property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public ObservableCollection<ALiteTeam.PackageTracer.Data.QueryResult.Detail> Details
        {
            get
            {
                return mDetails;
            }
            set
            {
                if (mDetails == value)
                {
                    return;
                }
                mDetails = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(DetailsPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="IsAutoRefresh" /> property's name.
        /// </summary>
        public const string IsAutoRefreshPropertyName = "IsAutoRefresh";
        private bool mIsAutoRefresh = false;

        /// <summary>
        /// Gets the IsAutoRefresh property.
        /// TODO Update documentation:
        /// Changes to that property's value raise the PropertyChanged event. 
        /// This property's value is broadcasted by the Messenger's default instance when it changes.
        /// </summary>
        public bool IsAutoRefresh
        {
            get
            {
                return mIsAutoRefresh;
            }
            set
            {
                if (mIsAutoRefresh == value)
                {
                    return;
                }
                mIsAutoRefresh = value;

                // Update bindings, no broadcast
                RaisePropertyChanged(IsAutoRefreshPropertyName);
            }
        }

        #endregion

        private void UpdateDetails(NotificationMessage message)
        {            
            // TODO: Toolkit bug, so use the following lines instead.
            //this.IsIndeterminate = true;
            if (message != null)
            {
                _PerfProgressBar = message.Target as Microsoft.Phone.Controls.PerformanceProgressBar;
                _PerfProgressBar.IsIndeterminate = true;
            }

            this.QueryOp.GetDetails();
        }

        public RelayCommand SaveCommand { get; private set; }
        private void Save()
        {
            // 若是开启自动更新操作，并且系统设置上还没有打开自动更新功能，则提示用户开启
            if (this.IsAutoRefresh == true && Settings.Configuration.AllowUpdateViaBackground == false)
            {
                if (MessageBox.Show("当前未开启后台更新功能，是否打开？", "提醒", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    ViewModelLocator.SettingsViewModelStatic.AllowUpdateViaBackground = true;
                    ViewModelLocator.SettingsViewModelStatic.AllowToast = true;

                    Messenger.Default.Send<bool>(true, SettingsViewModel.ENALBE_AUTOMATIC_UPDATE);
                }
            }

            _Order.IsAutoRefresh = this.IsAutoRefresh;
            _Order.RefreshDuration = this.RefreshDuration;

            this.OrderOp.UpdateOrder(_Order);
        }

        void QueryOp_QueryDetailsCompleted(object sender, QueryEventArgs e)
        {
            // 若网络访问成功
            if (e.Success == true && string.IsNullOrEmpty(e.Result) != true)
            {
                _Order.Details = e.Result;

                HandleDetails();
            }
            else
            {
                this.Details = new ObservableCollection<QueryResult.Detail>();

                this.Details.Add(new QueryResult.Detail() { Time = DateTime.Now, Context = "网络错误，查询失败，请稍候再试。", FTime = DateTime.Now });
            }

            _Order.LastDetailsUpdatedTime = DateTime.Now;
            this.OrderOp.UpdateOrder(_Order);

            // TODO:Toolkit bug, so use the following lines instead.
            //this.IsIndeterminate = false;
            if (_PerfProgressBar != null)
            {
                _PerfProgressBar.IsIndeterminate = false;
            }
        }

        private void Initialize(Guid id)
        {
            this._Order = OrderOp.GetOrderByID(id);
            this._Delivery = DeliveryOp.DeliveryResource.Deliveries.Where(e => e.ID == _Order.DeliveryID).FirstOrDefault();
            this.QueryOp = new QuerySvcOp(_Order);
            this.QueryOp.QueryDetailsCompleted += new EventHandler<QueryEventArgs>(QueryOp_QueryDetailsCompleted);

            // 为绑定属性赋值
            this.DisplayName = _Delivery.DisplayName;
            this.OrderNo = _Order.OrderNo;
            this.Title = _Order.Title;
            this.IsAutoRefresh = _Order.IsAutoRefresh;
            this.RefreshDuration = _Order.RefreshDuration;

            if (string.IsNullOrEmpty(_Order.Details) == false)
            {
                HandleDetails();
            }
            else
            {
                UpdateDetails(null);
            }
        }

        private void HandleDetails()
        {
            QueryResult resultDetails;

            try
            {
                resultDetails = QueryResult.ParseOrder(_Order.Details);
            }
            catch
            {
                resultDetails = new QueryResult()
                {
                    Status = 99,
                    Summary = "接收到的数据转换失败，请联系开发者更新API"
                };
            }

            if (resultDetails.Status == 1)
            {
                this.Details = new ObservableCollection<QueryResult.Detail>(resultDetails.Details);
            }
            else
            {
                var details = new ObservableCollection<QueryResult.Detail>();

                var index = resultDetails.Summary.IndexOf('，');
                var content = resultDetails.Summary.Substring(index + 1);
                details.Add(new QueryResult.Detail() { Time = DateTime.Now, Context = content, FTime = DateTime.Now });

                this.Details = details;
            }
        }
    }
}
